#pragma once
#include <iostream>
#include <memory>
#include <utility>
#include <stdexcept>
#include <shared_mutex>

 
namespace zcb
{
    std::shared_mutex _Shared_mutex;
    struct _ZCB_Container_base12;
    struct _ZCB_Container_proxy;
    class _ZCB_Iterator_base12;

	template <typename ClassType>
	struct SimpleTypes
    { // wraps types from allocators with simple addressing for use in iterators
		// and other SCARY machinery
		using class_type = ClassType;
		using size_type = unsigned long long;
		using difference_type = long long;
		using pointer = class_type*;
		using const_pointer = const class_type*;
	};

    struct _ZCB_Container_proxy { // store head of iterator chain and back pointer
        _CONSTEXPR20 _ZCB_Container_proxy() noexcept = default;
        _CONSTEXPR20 _ZCB_Container_proxy(_ZCB_Container_base12* _Mycont_) noexcept : _Mycont(_Mycont_) {}

        const _ZCB_Container_base12* _Mycont = nullptr;
        mutable _ZCB_Iterator_base12* _Myfirstiter = nullptr;
    };

    class _ZCB_Iterator_base12
    {

    public:
        _ZCB_Iterator_base12() = default;

        // 复制构造函数
        _ZCB_Iterator_base12(const _ZCB_Iterator_base12& _Right)
        {
            *this = _Right;
        }

    public:
        mutable _ZCB_Iterator_base12* _nextiter = nullptr;
        mutable _ZCB_Container_proxy* proxy = nullptr;

        void _Adopt_iterator_locked(_ZCB_Container_base12* vector_container)
        {
            std::unique_lock<std::shared_mutex> lock(_Shared_mutex);
            _Adopt_iterator_unlocked(vector_container);
        }

        void _Adopt_iterator_unlocked(const _ZCB_Container_base12* vector_container);

        void _Orphan_me_unlocked()
        {
            if (!proxy)
            {
                return;
            }

            // 获取链表每个节点的地址，然后遍历地址找到当前节点
            _ZCB_Iterator_base12** _next = &(proxy->_Myfirstiter);
            for (; _next; _next = &((**_next)._nextiter))
            {
                if (*_next == this)
                {
                    *_next = _nextiter;  // 将当前节点改为当前节点的下一节点
                    proxy = nullptr;  // 将迭代器与容器断开，即孤立
                    break;
                }
            }
            return;
        }

        void _Assign_iterator_locked(const _ZCB_Iterator_base12& _Other)
        {
            std::unique_lock<std::shared_mutex> lock(_Shared_mutex);
            _Assign_iterator_unlocked(_Other);
        }

        void _Assign_iterator_unlocked(const _ZCB_Iterator_base12& _Other)
        {
            if (_Other.proxy == this->proxy)
            {
                return;
            }

            if (_Other.proxy)
            {
                _Adopt_iterator_unlocked(_Other.proxy->_Mycont);
            }
            else
            {
                _Orphan_me_unlocked();
            }

        }

    public:
        _ZCB_Iterator_base12& operator=(const _ZCB_Iterator_base12& _Other)
        {
            _Assign_iterator_locked(_Other);
            return *this;
        }

    };

    struct _ZCB_Container_base12
    {
    public:
        _ZCB_Container_base12()
        {}

        template<typename _Alloc>
        constexpr void _Alloc_proxy(_Alloc&& _alloc)
        {
            _ZCB_Container_proxy* const new_proxy = _alloc.allocate(1);
            std::allocator_traits<_Alloc>::construct(_alloc, new_proxy, this);
            _Myproxy = new_proxy;
        }


        void _Orphan_all() const
        {
            _Orphan_all_locked();
        }

        void _Orphan_all_locked() const
        {
            std::unique_lock<std::shared_mutex> _lock(_Shared_mutex);
            _Orphan_all_unlocked();
        }

        void _Orphan_all_unlocked() const
        {
            // 若无代理，则说明肯定没有迭代器与容器关联
            if (!_Myproxy)
            {
                return;
            }

            // 遍历整个迭代器链表，断开迭代器和代理对象，从而将迭代器孤立于容器
            for (auto _Nextiter = _Myproxy->_Myfirstiter; _Nextiter != nullptr; _Nextiter = _Nextiter->_nextiter)
            {
                _Nextiter->proxy = nullptr;
            }
            return;
        }

        _ZCB_Container_proxy* _Myproxy = nullptr;
    };

    void _ZCB_Iterator_base12::_Adopt_iterator_unlocked(const _ZCB_Container_base12* vector_container)
    {
        // 如果数据容器不存在（即数据容器中没有数据时），直接孤立迭代器并返回
        if (!vector_container)
        {
            _Orphan_me_unlocked();
            return;
        }

        // 数据容器关联的代理对象
        _ZCB_Container_proxy* parent = vector_container->_Myproxy;

        // 判断当前迭代器代理是否等于容器代理，若不等于说明该迭代器可能关联在其他容器上，
        // 否则表示关联在同一容器上，注意一个迭代器只能关联在一个容器上
        if (proxy != parent)
        {
            if (proxy)  // 判断当前迭代器关联在其他容器上，则需将该迭代器从其他容器上孤立出来
            {
                _Orphan_me_unlocked();
            }
            _nextiter = parent->_Myfirstiter;
            parent->_Myfirstiter = this;
            proxy = parent;
        }
    }

    template<typename Ty>
    class _ZCB_Vector_const_iterator : public _ZCB_Iterator_base12
    {
    public:
        using pointer = typename Ty::pointer;
        using reference = typename Ty::reference;

        pointer ptr;  // 指向vector中的某一个数据指针

        _ZCB_Vector_const_iterator(pointer vector_data, _ZCB_Container_base12* vector_container)
            :ptr(vector_data)
        {
            _Adopt_iterator(vector_container);
        }

        void _Adopt_iterator(_ZCB_Container_base12* vector_container)
        {
            _Adopt_iterator_locked(vector_container);
        }

    public:
        reference operator*()
        {
            return *ptr;
        }

        _CONSTEXPR20 _ZCB_Vector_const_iterator& operator++() noexcept {
            ++ptr;
            return *this;
        }

    };

    template<typename Ty>
    class _ZCB_Vector_iterator : public _ZCB_Vector_const_iterator<Ty>
    {

        using _My_base = _ZCB_Vector_const_iterator<Ty>;
        using _My_base::_My_base;
        using pointer = typename Ty::pointer;
        
        using reference = typename Ty::reference;

    public:
        reference operator*()
        {
            return _My_base::operator*();
        }

        _CONSTEXPR20 _ZCB_Vector_iterator& operator++() noexcept {
            _My_base::operator++();
            return *this;
        }

        _CONSTEXPR20 _ZCB_Vector_iterator operator++(int) noexcept {
            _ZCB_Vector_iterator tmp = *this;
            _My_base::operator++();
            return *this;
        }
    };

    template <typename ValTypes>
    class VectorVal: public _ZCB_Container_base12
    {
    public:
        using class_type = typename ValTypes::class_type;  // 因为class_type是模板参数，因此需要加typename
        using size_type = typename ValTypes::size_type;
        using difference_type = typename ValTypes::difference_type;
        using pointer = typename ValTypes::pointer;
        using const_pointer = typename ValTypes::const_pointer;
        using reference = class_type&;
        using const_reference = const class_type&;

        pointer myFirst; // pointer to beginning of array
        pointer myLast; // pointer to current end of sequence
        pointer myEnd; // pointer to end of array

        constexpr VectorVal() noexcept : myFirst(), myLast(), myEnd()
        {
            std::cout << "create VectorVal\n";
        }

        constexpr VectorVal(pointer _First, pointer _Last, pointer _End) noexcept
            : myFirst(_First), myLast(_Last), myEnd(_End) {}

    };
	

    template<typename Ty1, typename Ty2>
    class Rebind_Alloc_Class
    {

    public:
        using AllocType = typename Ty1;
        using ClassType = typename Ty2;
        using AllocatorTraits = std::allocator_traits<AllocType>;

    public:
        Ty1 _alloc;
        Ty2 *_classObj;

    public:
        Rebind_Alloc_Class()
            :_alloc(), _classObj(nullptr)
        {
            std::cout << "create Rebind_Alloc_Class\n";
            _classObj = _alloc.allocate(1);
        }

        void construct_ClassObj(ClassType&& value,
            ClassType* const loc)
        {
            AllocatorTraits::construct(_alloc, loc, std::forward<ClassType>(value));
        }

        void dealloc(ClassType* ptr, size_type& count)
        {
            AllocatorTraits::deallocate(_alloc, ptr, count);
        }

        void _destroy_range(ClassType* p1, ClassType* p2)
        {
            for (ClassType* i = p1; i != p2; ++i)
            {
                AllocatorTraits::destroy(_alloc, i);
            }
        }

    };


    template<typename Ty1, typename Ty2>
    class CompressedPair: private Ty1
    {
    public:
        using size_type = ::uint64_t;

    public:
        Ty2 myVals;

        template<typename... ArgsType2>
        CompressedPair(ArgsType2&&... args2)
            :Ty1(), myVals(std::forward<ArgsType2>(args2)...)
        {
            std::cout << "create CompressedPair\n";
            myVals.myFirst = this->_classObj;
            myVals.myLast = this->_classObj;
            myVals.myEnd = myVals.myFirst + 1;
        }

        _NODISCARD constexpr typename Ty1::ClassType* alloc_space(const size_type& count)
        {
            return this->_alloc.allocate(count);
        }

        void dealloc_sapce(typename Ty1::ClassType* ptr, size_type& count)
        {
            this->dealloc(ptr, count);
        }

        void destroy_range(typename Ty1::ClassType* _first, typename Ty1::ClassType* _last)
        {
            this->_destroy_range(_first, _last);
        }

        // 原地构造分类器Ty1中接受的类ClassType
        void construct_2(typename Ty1::ClassType&& value,
            typename Ty1::ClassType* const loc)
        {
            this->construct_ClassObj(std::forward<typename Ty1::ClassType>(value), loc);
        }

    };



	template <typename DataType, typename _Alloc = std::allocator<DataType>>
	class vector
    {
    public:

        // 为什么不需要加typename，因为VectorVal是一个模板类，
        // 如果是为一个模板参数弄别名，需要加typename
		using ScaryVal = VectorVal<std::conditional_t<true, SimpleTypes<DataType>,
            SimpleTypes<DataType>>>; // 最后的SimpleTypes<DataType>暂定，暂时占个位置

        using size_type = ::uint64_t;
        using pointer = typename DataType*;

        // 为vector接受的数据类型提供内存分配器
        using Alty = Rebind_Alloc_Class<_Alloc, DataType>;
        
        // 为代理类提供内存分配器
        using _Proxy_alloc = std::allocator<_ZCB_Container_proxy>;

        
        using iterator = _ZCB_Vector_iterator<ScaryVal>;  // 普通迭代器
        using const_iterator = _ZCB_Vector_const_iterator<ScaryVal>;  // 常量迭代器

        CompressedPair<Alty, ScaryVal> myPairs;

        vector()
            :myPairs()
        {
            std::cout << "create vector\n";
            myPairs.myVals._Alloc_proxy(_Proxy_alloc());
        }
  
        void push_back(const DataType& value)
        {
            
        }

        void push_back(DataType&& value)
        {
            auto& myData = myPairs.myVals;

            if (myData.myLast != myData.myEnd)
            {
                _Emplace_back_with_unused_capacity(std::forward<DataType>(value));
                return;
            }

            _Emplace_reallocate(std::forward<DataType>(value));
        }

        constexpr size_type capacity()
        {
            return static_cast<size_type>(myPairs.myVals.myEnd - myPairs.myVals.myFirst);
        }


        void clear()
        {
            auto& myData = myPairs.myVals;
            if (myData.myFirst == myData.myLast)
            {
                return;
            }

            myPairs.destroy_range(myData.myFirst, myData.myLast);
            myData.myLast = myData.myFirst;
        }


        void resize(size_type _new_size)
        {
            if(_new_size > 0)
                _resize_range(_new_size);
        }

        void resize(size_type new_size, DataType value)
        {
            //暂定
        }

        // 获取vector的元素个数
        size_type size() const
        {
            return static_cast<size_type>(myPairs.myVals.myLast - myPairs.myVals.myFirst);
        }

        // 据官方文档，const放在函数声明末尾时，视作为同名函数的重载（即使参数一样），注意：函数重载与返回类型无关
        // 构造常量迭代器
        const_iterator begin() const
        {

        }

        // 构造普通迭代器，并获取指向第一个元素的迭代器
        iterator begin()
        {
            auto& _Mydata = myPairs.myVals;
            return iterator(_Mydata.myFirst, &_Mydata);
        }


    private:
        void _resize_range(size_type& _new_size)
        {
            auto& myData = myPairs.myVals;
            size_type _old_size = static_cast<size_type>(myData.myLast - myData.myFirst);
            
            if ( _new_size < _old_size )
            {
                pointer new_last = myData.myFirst + _new_size;
                myPairs.destroy_range(new_last, myData.myLast);
                myData.myLast = new_last;
            }

            if ( _new_size > _old_size  )
            {
                size_type _capacity = capacity();
                if ( _new_size > _capacity )
                {
                    _resize_alloc(_new_size);
                    return;
                }

                pointer new_last = myData.myFirst + _new_size;
                _zero_range(myData.myLast, new_last);
                myData.myLast = new_last;
            }
        }

        template<typename Ty>
        void _zero_range(Ty* _first, Ty* _last)
        {
            char* const _first_ch = reinterpret_cast<char*>(std::_To_address(_first));
            char* const _last_ch = reinterpret_cast<char*>(std::_To_address(_last));
            std::memset(_first_ch, 0, _last_ch - _first_ch);
        }

        // 处理resize函数调用的内存分配函数
        void _resize_alloc(size_type& _new_size)
        {
            size_type _cap = _calculate_capacity(_new_size);
            auto& myData = myPairs.myVals;
            pointer _first = myData.myFirst;
            pointer _last = myData.myLast;
            size_type size = _last - _first;

            myData.myFirst = myPairs.alloc_space(_cap);
            myData.myLast = myData.myFirst;
            myData.myEnd = myData.myFirst + _cap;

            for (pointer i = _first; i != _last; ++i)
            {
                myPairs.construct_2(std::move(*i), myData.myLast);
                ++myData.myLast;
            }

            myPairs.dealloc_sapce(_first, size);

        }

        // 计算容量函数
        size_type _calculate_capacity(size_type _new_size)
        {
            auto& myData = myPairs.myVals;
            size_type old_capacity = capacity();
            if (old_capacity + old_capacity / 2 >= INT64_MAX)
            {
                _too_len();
            }
            size_type _Geometric = old_capacity + old_capacity / 2;

            if (_Geometric < _new_size)
            {
                return _new_size;
            }

            return _Geometric;
        }

        // 处理push_back的内存分配函数
        void _Emplace_reallocate(DataType&& values)
        {
            auto& myData = myPairs.myVals;
            pointer myFirst = myData.myFirst;
            pointer myEnd = myData.myEnd;

            size_type count = myEnd - myFirst;

            size_type new_capacity = _calculate_capacity(count + 1);

            myData.myFirst = myPairs.alloc_space(new_capacity);

            // 孤立所有迭代器
            myData._Orphan_all();

            myData.myLast = myData.myFirst;
            myData.myEnd = myData.myFirst + new_capacity;

            for (pointer i = myFirst; i != myEnd; ++i)
            {
                myPairs.construct_2(std::move(*i), myData.myLast);
                myData.myLast += 1;
            }

            myPairs.dealloc_sapce(myFirst, count);

            myPairs.construct_2(std::forward<DataType>(values), myData.myLast);
            myData.myLast += 1;
        }

        // 孤立范围内的迭代器
         constexpr void _Orphan_range(pointer _first, pointer _last)
        {
            _Orphan_range_locked(_first, _last);
        }

        // 若处于多线程，则对同一个容器进行增删改查时，针对孤立容器过程需要加锁
        constexpr void _Orphan_range_locked(pointer _first, pointer _last)
        {
            // 加独占锁，只允许一个线程进入   
            std::unique_lock<std::shared_mutex> lock(_Shared_mutex);
            _Orphan_range_unlocked(_first, _last);
        }

        // 若在编译时需要孤立，则不需要加锁，因为编译阶段不存在多线程临界区争夺
        constexpr void _Orphan_range_unlocked(pointer _first, pointer _last)
        {
            // 之所以需要使用二次指针，是因为我们需要更改原链表，因此需要获得原链表的节点的地址
            _ZCB_Iterator_base12** _Next_iter = &myPairs.myVals._Myproxy->_Myfirstiter;
            while (*_Next_iter)
            {
                auto ptr = static_cast<_ZCB_Vector_const_iterator<ScaryVal>>(**_Next_iter).ptr;
                if (ptr < _first || ptr > _last)
                {
                    _Next_iter = &((*_Next_iter)->_nextiter);
                }
                else
                {
                    (*_Next_iter)->proxy = nullptr;  // 孤立迭代器
                    *_Next_iter = (*_Next_iter)->_nextiter;  // 将当前迭代器节点从总迭代器链表中去除
                }
            }
        }

        void _Emplace_back_with_unused_capacity(DataType&& values)
        {
            auto& myData = myPairs.myVals;
            pointer insert_loc = myData.myLast;
            myPairs.construct_2(std::forward<DataType>(values), insert_loc);
            myData.myLast += 1;
        }

    public:
        DataType& operator[](const size_type& index)
        {
            if (index < 0 || index + myPairs.myVals.myFirst >= myPairs.myVals.myEnd)
            {
                _out_range();
            }
            return myPairs.myVals.myFirst[index];
        }


    private:
        [[noreturn]] inline void _too_len() const
        {
            throw std::bad_alloc();
        }

        [[noreturn]] inline void _out_range() const
        {
            throw std::out_of_range("Index is out of range");
        }
      	};

}